From 3350e93244f71a021522d18082c13efdd478cf5c Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Sun, 16 Mar 2003 11:18:06 +0000 Subject: [PATCH] bitkeeper revision 1.137 (3e745d6egPhbuKyLs12XPZOtKEunKA) schedule.c, ac_timer.c, time.c, apic.c: Some timer fixes. --- xen/arch/i386/apic.c | 51 +++++++++++++++++++++++-------------------- xen/arch/i386/time.c | 25 +++++++++++---------- xen/common/ac_timer.c | 16 +++++++------- xen/common/schedule.c | 7 +++--- 4 files changed, 52 insertions(+), 47 deletions(-) diff --git a/xen/arch/i386/apic.c b/xen/arch/i386/apic.c index 2621bd1109..e8e25e7f17 100644 --- a/xen/arch/i386/apic.c +++ b/xen/arch/i386/apic.c @@ -19,15 +19,15 @@ */ /* - * Local APIC handling, local APIC timers + * Local APIC handling, local APIC timers * - * (c) 1999, 2000 Ingo Molnar + * (c) 1999, 2000 Ingo Molnar * - * Fixes - * Maciej W. Rozycki : Bits for genuine 82489DX APICs; - * thanks to Eric Gilmore - * and Rolf G. Tews - * for testing these extensively. + * Fixes + * Maciej W. Rozycki : Bits for genuine 82489DX APICs; + * thanks to Eric Gilmore + * and Rolf G. Tews + * for testing these extensively. */ @@ -329,13 +329,13 @@ void __init setup_local_APIC (void) value = APIC_DM_NMI; else value = APIC_DM_NMI | APIC_LVT_MASKED; - if (!APIC_INTEGRATED(ver)) /* 82489DX */ + if (!APIC_INTEGRATED(ver)) /* 82489DX */ value |= APIC_LVT_LEVEL_TRIGGER; apic_write_around(APIC_LVT1, value); - if (APIC_INTEGRATED(ver)) { /* !82489DX */ + if (APIC_INTEGRATED(ver)) { /* !82489DX */ maxlvt = get_maxlvt(); - if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */ + if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */ apic_write(APIC_ESR, 0); value = apic_read(APIC_ESR); printk("ESR value before enabling vector: %08lx\n", value); @@ -653,25 +653,28 @@ void __init setup_APIC_clocks (void) */ int reprogram_ac_timer(s_time_t timeout) { - int cpu = smp_processor_id(); - s_time_t now; - s_time_t expire; - u64 apic_tmict; - - if (timeout == 0) { - /* XXX RN: not sure if this disables it or cause interruptto - * go off imediately */ - apic_tmict = 0; + int cpu = smp_processor_id(); + s_time_t now; + s_time_t expire; + u64 apic_tmict; + + /* + * We use this value because we don't trust zero (we think it may just + * cause an immediate interrupt). At least this is guaranteed to hold it + * off for ages (esp. since the clock ticks on bus clock, not cpu clock!). + */ + if (timeout == 0) { + apic_tmict = 0xffffffff; goto reprogram; } now = NOW(); - expire = timeout - now; /* value from now */ + expire = timeout - now; /* value from now */ if (expire <= 0) { printk("APICT[%02d] Timeout in the past 0x%08X%08X > 0x%08X%08X\n", cpu, (u32)(now>>32), (u32)now, (u32)(timeout>>32),(u32)timeout); - return 0; /* timeout value in the past */ + return 0; /* timeout value in the past */ } /* conversion to bus units */ @@ -687,7 +690,7 @@ int reprogram_ac_timer(s_time_t timeout) } reprogram: - /* programm timer */ + /* Program the timer. */ apic_write(APIC_TMICT, (unsigned long)apic_tmict); TRC(printk("APICT[%02d] reprog(): expire=%lld %u\n", @@ -755,9 +758,9 @@ void smp_apic_timer_interrupt(struct pt_regs * regs) */ ack_APIC_irq(); - /* call the local handler */ + /* call the local handler */ irq_enter(cpu, 0); - perfc_incrc(apic_timer); + perfc_incrc(apic_timer); smp_local_timer_interrupt(regs); irq_exit(cpu, 0); diff --git a/xen/arch/i386/time.c b/xen/arch/i386/time.c index 773c4cfeb3..d03767ef2b 100644 --- a/xen/arch/i386/time.c +++ b/xen/arch/i386/time.c @@ -240,15 +240,12 @@ static u32 st_scale_i; u32 stime_pcc; /* cycle counter value at last timer irq */ s_time_t stime_now; /* time in ns at last timer IRQ */ -s_time_t get_s_time(void) +static inline s_time_t __get_s_time(void) { - unsigned long flags; u32 delta_tsc, low, pcc; u64 delta; s_time_t now; - spin_lock_irqsave(&stime_lock, flags); - pcc = stime_pcc; now = stime_now; @@ -259,9 +256,17 @@ s_time_t get_s_time(void) delta >>= 32; delta += ((u64)delta_tsc * st_scale_i); - spin_unlock_irqrestore(&stime_lock, flags); + return now + delta; +} - return now + delta; +s_time_t get_s_time(void) +{ + s_time_t now; + unsigned long flags; + spin_lock_irqsave(&stime_lock, flags); + now = __get_s_time(); + spin_unlock_irqrestore(&stime_lock, flags); + return now; } @@ -326,17 +331,13 @@ static struct ac_timer update_timer; static void update_time(unsigned long foo) { unsigned long flags; - u32 new_pcc; s_time_t new_st; unsigned long usec; - new_st = NOW(); - rdtscl(new_pcc); - /* Update system time. */ spin_lock_irqsave(&stime_lock, flags); - stime_now = new_st; - stime_pcc=new_pcc; + stime_now = new_st = __get_s_time(); + rdtscl(stime_pcc); /* Don't reeenable IRQs until we release wctime_lock. */ spin_unlock(&stime_lock); diff --git a/xen/common/ac_timer.c b/xen/common/ac_timer.c index 73ac893e08..4505712bf3 100644 --- a/xen/common/ac_timer.c +++ b/xen/common/ac_timer.c @@ -82,7 +82,9 @@ int add_ac_timer(struct ac_timer *timer) (u32)(timer->expires>>32), (u32)timer->expires)); return 1; } + spin_lock_irqsave(&ac_timers[cpu].lock, flags); + /* * Add timer to the list. If it gets added to the front we have to * reprogramm the timer @@ -154,8 +156,12 @@ int rem_ac_timer(struct ac_timer *timer) /* just removed the head */ if (list_empty(&ac_timers[cpu].timers)) { reprogram_ac_timer((s_time_t) 0); + } else { + timer = list_entry(ac_timers[cpu].timers.next, + struct ac_timer, timer_list); + if ( timer->expires > (NOW() + TIMER_SLOP) ) + reprogram_ac_timer(timer->expires); } - /* XXX should actaully reprogramm APIC to new head */ } } else res = -1; @@ -201,13 +207,7 @@ void do_ac_timer(void) /* Sanity: is the timer list empty? */ if ( list_empty(&ac_timers[cpu].timers) ) { - /* - * XXX RN: This shouldn't happen, but does! Two possibilities: - * - Race condition between removing and reseting APIC - * - setting an APIC timeout value of 0 causes an immediate - * timer interrupt to fire. - * None of these should be critical! - */ + /* This does sometimes happen: race condition in resetting timeout? */ spin_unlock_irqrestore(&ac_timers[cpu].lock, flags); return; } diff --git a/xen/common/schedule.c b/xen/common/schedule.c index 3ef29e3c5c..9842036c98 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -368,9 +368,9 @@ asmlinkage void schedule(void) sched_done: ASSERT(r_time != 0); - ASSERT(r_time > ctx_allow); + ASSERT(r_time >= ctx_allow); -#if 0 +#ifndef NDEBUG if ( (r_time==0) || (r_time < ctx_allow)) { printk("[%02d]: %lx\n", this_cpu, r_time); dump_rqueue(&schedule_data[this_cpu].runqueue, "foo"); @@ -389,7 +389,8 @@ asmlinkage void schedule(void) timer_redo: schedule_data[this_cpu].s_timer.expires = now + r_time; if (add_ac_timer(&schedule_data[this_cpu].s_timer) == 1) { - printk("SCHED[%02d]: Shit this shouldn't happen\n", this_cpu); + printk("SCHED[%02d]: Shit this shouldn't happen %08x\n", + this_cpu, r_time); now = NOW(); goto timer_redo; } -- 2.30.2